# -*- coding: utf-8 -*-

import paramiko
import os
from paramiko.ssh_exception import AuthenticationException, SSHException

from ioloop import IOLoop

from ..cheungssh_modul_controler import CheungSSHControler
from ..cheungssh_settings  import keyfile_dir

class Bridge(object):
    '''websocket 客户端和　ssh 服务端的链接'''
    def __init__(self, websocket):
        self._websocket = websocket
        self._shell = None
        self._id = 0
        self.ssh = paramiko.SSHClient()

    @property
    def id(self):
        return self._id

    @property
    def websocket(self):
        return self._websocket

    @property
    def shell(self):
        return self._shell

    def open(self, data={}):
        server_config = CheungSSHControler.convert_id_to_ip(data['sid'])
        if not server_config["status"]:
            self._websocket.write_message(server_config["content"])
            return
        kws = server_config["content"]
        try:
            self.owner = kws["owner"]
            self.su = kws["su"]
            self.sudo = kws["sudo"]
            self.username = kws["username"]
            self.password = kws["password"]
            self.port = kws["port"]
            self.login_method = kws["login_method"]
            self.ip = kws["ip"]
            self.keyfile = os.path.join(keyfile_dir, self.owner, kws["keyfile"])
            self.keyfile_password = kws["keyfile_password"]
            self.sudo = kws["sudo"]
            self.sudo_password = kws["sudo_password"]
            self.su = kws["su"]
            self.su_password = kws["su_password"]
            self.port = int(self.port)
            ssh = paramiko.SSHClient()
            if self.login_method == 'PASSWORD':
                ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                ssh.connect(self.ip, self.port, self.username, self.password)
            else:
                if len(self.keyfile_password) > 0 and not self.keyfile_password == "******":
                    key = paramiko.RSAKey.from_private_key_file(self.keyfile, password=self.keyfile_password)
                else:
                    key = paramiko.RSAKey.from_private_key_file(self.keyfile)
                ssh.load_system_host_keys()
                ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                ssh.connect(self.ip, self.port, self.username, pkey=key)
            self.ssh = ssh
        except AuthenticationException:
            raise Exception("auth failed user:%s ,passwd:%s" %
                            (data["username"], data["password"]))
        except SSHException:
            raise Exception("could not connect to host:%s:%s" %
                            (data["hostname"], data["port"]))

        self.establish()

    def establish(self, term="xterm"):
        self._shell = self.ssh.invoke_shell(term)
        self._shell.setblocking(0)

        self._id = self._shell.fileno()
        IOLoop.instance().register(self)
        IOLoop.instance().add_future(self.trans_back())

    def trans_forward(self, data=""):
        if self._shell:
            self._shell.send(data)

    def trans_back(self):
        yield self.id
        connected = True
        while connected:
            result = yield
            if self._websocket:
                try:
                    self._websocket.write_message(result)
                except Exception:
                    connected = False
                if result.strip() == 'logout':
                    connected = False
        self.destroy()

    def destroy(self):
        self._websocket.close()
        self.ssh.close()
